﻿namespace wToggle.Platform.Data
{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Linq;
    using System.Runtime.CompilerServices;
    using System.Runtime.Serialization;
    using System.Threading.Tasks;

    using Windows.UI.Core;
    using Windows.UI.Xaml;

    using wToggle.Platform.Annotations;
    using wToggle.Platform.Interfaces;

    using XPlatUtils;

    [DataContract]
    public sealed class TimeEntry : IEntity
    {
        public TimeEntry()
        {
            this.SetDefaults();
        }

        [OnDeserializing]
        public void OnDeserializing(StreamingContext context)
        {
            this.SetDefaults();
        }

        private void SetDefaults()
        {
            this.TagIds = new List<string>();
        }

        [DataMember(Name = "id", EmitDefaultValue = false)]
        public ulong Id { get; set; }

        [DataMember(Name = "pid", EmitDefaultValue = false)]
        public ulong ProjectId { get; set; }

        [DataMember(Name = "wid")]
        public ulong WorkspaceId { get; set; }

        [DataMember(Name = "billable")]
        public bool IsBillable { get; set; }

        [DataMember(Name = "start")]
        public string StartIso { get; set; }

        [DataMember(Name = "duration")]
        public int Duration { get; set; }

        [DataMember(Name = "description", EmitDefaultValue = false)]
        public string Description { get; set; }
        
        [DataMember(Name = "tags")]
        public List<string> TagIds { get; set; }

        [DataMember(Name = "created_with", EmitDefaultValue = false)]
        public string CreatedWith { get; set; }

        [IgnoreDataMember]
        public string DurationString
        {
            get
            {
                var ts = TimeSpan.FromSeconds(this.Duration);

                return ts.ToDurationString();
            }
        }


        [IgnoreDataMember]
        public Project Project { get; private set; }

        [IgnoreDataMember]
        public string TagString
        {
            get
            {
                if (this.TagIds != null && this.TagIds.Any())
                {
                    return string.Join(", ", this.TagIds);
                }

                return string.Empty;
            }
        }

        [IgnoreDataMember]
        public DateTime? Start
        {
            get
            {
                if (string.IsNullOrEmpty(this.StartIso))
                {
                    return null;
                }

                return DateTime.Parse(this.StartIso);
            }
        }

        [IgnoreDataMember]
        public string ReadableDescription
        {
            get
            {
                if (string.IsNullOrEmpty(this.Description))
                {
                    return "(no description)";
                }

                return this.Description;
            }
        }

        [IgnoreDataMember]
        public DateTime? End
        {
            get
            {
                if (this.Start == null)
                {
                    return null;
                }

                return this.Start.Value.Add(TimeSpan.FromSeconds(this.Duration));
            }
        }

        public async Task ExpandProject()
        {
            if (this.ProjectId <= 0)
            {
                return;
            }

            var provider = ServiceContainer.Resolve<IProjectProvider>();
            this.Project = await provider.GetProject(this.ProjectId);
        }
    }

    [DataContract]
    public sealed class ReportTimeEntry
    {
        public ReportTimeEntry()
        {
            this.SetDefaults();
        }

        [OnDeserializing]
        public void OnDeserializing(StreamingContext context)
        {
            this.SetDefaults();
        }

        private void SetDefaults()
        {
            this.TagIds = new List<string>();
        }

        [DataMember(Name = "id", EmitDefaultValue = false)]
        public ulong Id { get; set; }

        [DataMember(Name = "pid", EmitDefaultValue = false)]
        public ulong ProjectId { get; set; }

        [DataMember(Name = "wid")]
        public ulong WorkspaceId { get; set; }

        [DataMember(Name = "billable")]
        public bool IsBillable { get; set; }

        [DataMember(Name = "start")]
        public string StartIso { get; set; }

        [DataMember(Name = "dur")]
        public int Duration { get; set; }

        [DataMember(Name = "description", EmitDefaultValue = false)]
        public string Description { get; set; }

        [DataMember(Name = "tags")]
        public List<string> TagIds { get; set; }

        [DataMember(Name = "created_with", EmitDefaultValue = false)]
        public string CreatedWith { get; set; }

        [IgnoreDataMember]
        public string DurationString
        {
            get
            {
                var ts = TimeSpan.FromMilliseconds(this.Duration);

                return ts.ToDurationString();
            }
        }


        [IgnoreDataMember]
        public Project Project { get; private set; }

        [IgnoreDataMember]
        public string TagString
        {
            get
            {
                if (this.TagIds != null && this.TagIds.Any())
                {
                    return string.Join(", ", this.TagIds);
                }

                return string.Empty;
            }
        }

        [IgnoreDataMember]
        public DateTime? Start
        {
            get
            {
                if (string.IsNullOrEmpty(this.StartIso))
                {
                    return null;
                }

                return DateTime.Parse(this.StartIso);
            }
        }

        [IgnoreDataMember]
        public string ReadableDescription
        {
            get
            {
                if (string.IsNullOrEmpty(this.Description))
                {
                    return "(no description)";
                }

                return this.Description;
            }
        }

        [IgnoreDataMember]
        public DateTime? End
        {
            get
            {
                if (this.Start == null)
                {
                    return null;
                }

                return this.Start.Value.Add(TimeSpan.FromSeconds(this.Duration));
            }
        }

        public async Task ExpandProject()
        {
            if (this.ProjectId <= 0)
            {
                return;
            }

            var provider = ServiceContainer.Resolve<IProjectProvider>();
            this.Project = await provider.GetProject(this.ProjectId);
        }
    }
}
